package android.slc.box.core.launcher;

import android.slc.box.core.controller.EventPlusHandler;
import android.slc.box.core.utils.StageUtils;
import android.slc.box.core.utils.ViewUtils;
import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.annotations.Nullable;
import javafx.application.Platform;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

/**
 * 窗口启动配置
 * 1.giveStage()
 * 2.initStage()
 * 3.syncStageParams/setStageParams
 * 4.applySingleOwnerMechanism
 */
public interface StageLauncherConfig {
    /**
     * 赋予宿主窗口和当前窗口
     * 宿主窗口可以为空，因为首次启动时只有当前窗口没有宿主窗口
     *
     * @param ownerStage
     * @param currentStage
     */
    default void giveStage(@Nullable Stage ownerStage, @NonNull Stage currentStage) {
        initStage(ownerStage, currentStage);
        if (isSyncStageParams()) {
            syncStageParams(ownerStage, currentStage, SyncType.SYNC_TYPE_ENTER);
        } else {
            setStageParams(currentStage);
            Platform.runLater(() -> {
                setStageParamsRunLast(currentStage);
            });
        }
        if (isApplySingleOwnerMechanism()) {
            Platform.runLater(() -> {
                applySingleOwnerMechanism(ownerStage, currentStage);
            });
        }
    }

    /**
     * 初始化窗口
     * 配置窗口风格、图标、标题等等
     *
     * @param ownerStage
     * @param currentStage
     */
    default void initStage(@Nullable Stage ownerStage, @NonNull Stage currentStage) {

    }

    /**
     * 设置窗口参数
     * 当不需要同步上个窗口参数时调用，可在此处设置窗口的大小、位置等等
     * 此处可设置不受布局影响的参数，如位置、最大化、是否可改变大小等等
     *
     * @param currentStage
     */
    default void setStageParams(@NonNull Stage currentStage) {
    }

    /**
     * 设置窗口参数，设置在javaFxUI现场运行完之后在运行
     * 此处设置受布局参数所影响的参数如最小窗口大小、最大窗口大小等等
     *
     * @param currentStage
     */
    default void setStageParamsRunLast(@NonNull Stage currentStage) {
    }

    /**
     * 同步窗口参数
     * 默认实现，同步了最小大小、最大化、宽高、位置等等
     *
     * @param srcStage
     * @param targetStage
     * @param syncType
     */
    default void syncStageParams(@Nullable Stage srcStage, @NonNull Stage targetStage, SyncType syncType) {
        if (srcStage == null) {
            setStageParams(targetStage);
            Platform.runLater(() -> {
                setStageParamsRunLast(targetStage);
            });
            return;
        }
        if (srcStage.isMaximized()) {
            targetStage.setMaximized(srcStage.isMaximized());
        } else {
            targetStage.setMaximized(false);
        }
        if (targetStage.getX() != srcStage.getX()) {
            targetStage.setX(srcStage.getX());
        }
        if (targetStage.getY() != srcStage.getY()) {
            targetStage.setY(srcStage.getY());
        }
        Platform.runLater(() -> {
            syncStageParamsRunLast(srcStage, targetStage, syncType);
        });
    }

    default void syncStageParamsRunLast(@Nullable Stage srcStage, @NonNull Stage targetStage, SyncType syncType) {
        if (srcStage == null) {
            return;
        }
        targetStage.setWidth(srcStage.getWidth());
        targetStage.setHeight(srcStage.getHeight());
        targetStage.setMinWidth(srcStage.getMinWidth());
        targetStage.setMinHeight(srcStage.getMinHeight());
        targetStage.setMaxWidth(srcStage.getMaxWidth());
        targetStage.setMaxHeight(srcStage.getMaxHeight());
    }

    /**
     * 是否同步窗口参数
     *
     * @return
     */
    default boolean isSyncStageParams() {
        return false;
    }

    /**
     * 应用隐藏所有者
     * 在同一时刻只可显示一个窗口时使用
     */
    default void applySingleOwnerMechanism(@Nullable final Stage ownerStage, @NonNull final Stage currentStage) {
        if (ownerStage == null) {
            return;
        }
        ownerStage.hide();
        StageUtils.addOnWindowCloseRequest(currentStage, new EventPlusHandler.EventPlusHandlerListener() {
            @Override
            public boolean handle(WindowEvent event) {
                onWindowCloseEventHandler(event, ownerStage, currentStage);
                return true;
            }

            @Override
            public int getPriority() {
                return EventPlusHandler.EventPlusHandlerListener.PRIORITY_LOWEST;
            }
        });
    }

    default void onWindowCloseEventHandler(WindowEvent event, final Stage ownerStage, final Stage currentStage) {
        syncStageParams(currentStage, ownerStage, SyncType.SYNC_TYPE_EXIT);
        ownerStage.show();
    }

    default boolean isApplySingleOwnerMechanism() {
        return false;
    }

    enum SyncType {
        SYNC_TYPE_ENTER,
        SYNC_TYPE_EXIT
    }
}
